/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.com/javaexamples2.
 */

package gui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.awt.Insets;
import java.awt.LayoutManager2;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * This LayoutManager arranges the components into a column. Components are
 * always given their preferred size.
 * 
 * When you create a ColumnLayout, you may specify four values: margin_height --
 * how much space to leave on top and bottom margin_width -- how much space to
 * leave on left and right spacing -- how much vertical space to leave between
 * items alignment -- the horizontal position of the components:
 * ColumnLayout.LEFT -- left-justify the components ColumnLayout.CENTER --
 * horizontally center the components ColumnLayout.RIGHT -- right-justify the
 * components
 * 
 * You never call the methods of a ColumnLayout object. Just create one and make
 * it the layout manager for your container by passing it to the addLayout()
 * method of the Container object.
 */
public class ColumnLayout implements LayoutManager2 {
	protected int margin_height;

	protected int margin_width;

	protected int spacing;

	protected int alignment;

	// Constants for the alignment argument to the constructor.
	public static final int LEFT = 0;

	public static final int CENTER = 1;

	public static final int RIGHT = 2;

	/** The constructor. See comment above for meanings of these arguments */
	public ColumnLayout(int margin_height, int margin_width, int spacing,
			int alignment) {
		this.margin_height = margin_height;
		this.margin_width = margin_width;
		this.spacing = spacing;
		this.alignment = alignment;
	}

	/**
	 * A default constructor that creates a ColumnLayout using 5-pixel margin
	 * width and height, 5-pixel spacing, and left alignment
	 */
	public ColumnLayout() {
		this(5, 5, 5, LEFT);
	}

	/**
	 * The method that actually performs the layout. Called by the Container
	 */
	public void layoutContainer(Container parent) {
		Insets insets = parent.getInsets();
		Dimension parent_size = parent.getSize();
		Component kid;
		int nkids = parent.getComponentCount();
		int x0 = insets.left + margin_width; // The base X position
		int x;
		int y = insets.top + margin_height; // Start at the top of the column

		for (int i = 0; i < nkids; i++) { // Loop through the kids
			kid = parent.getComponent(i); // Get the kid
			if (!kid.isVisible())
				continue; // Skip hidden ones
			Dimension pref = kid.getPreferredSize(); // How big is it?
			switch (alignment) { // Compute X coordinate
			default:
			case LEFT:
				x = x0;
				break;
			case CENTER:
				x = (parent_size.width - pref.width) / 2;
				break;
			case RIGHT:
				x = parent_size.width - insets.right - margin_width
						- pref.width;
				break;
			}
			// Set the size and position of this kid
			kid.setBounds(x, y, pref.width, pref.height);
			y += pref.height + spacing; // Get Y position of the next one
		}
	}

	/** The Container calls this to find out how big the layout should to be */
	public Dimension preferredLayoutSize(Container parent) {
		return layoutSize(parent, 1);
	}

	/** The Container calls this to find out how big the layout must be */
	public Dimension minimumLayoutSize(Container parent) {
		return layoutSize(parent, 2);
	}

	/** The Container calls this to find out how big the layout can be */
	public Dimension maximumLayoutSize(Container parent) {
		return layoutSize(parent, 3);
	}

	// Compute min, max, or preferred size of all the visible children
	protected Dimension layoutSize(Container parent, int sizetype) {
		int nkids = parent.getComponentCount();
		Dimension size = new Dimension(0, 0);
		Insets insets = parent.getInsets();
		int num_visible_kids = 0;

		// Compute maximum width and total height of all visible kids
		for (int i = 0; i < nkids; i++) {
			Component kid = parent.getComponent(i);
			Dimension d;
			if (!kid.isVisible())
				continue;
			num_visible_kids++;
			if (sizetype == 1)
				d = kid.getPreferredSize();
			else if (sizetype == 2)
				d = kid.getMinimumSize();
			else
				d = kid.getMaximumSize();
			if (d.width > size.width)
				size.width = d.width;
			size.height += d.height;
		}

		// Now add in margins and stuff
		size.width += insets.left + insets.right + 2 * margin_width;
		size.height += insets.top + insets.bottom + 2 * margin_height;
		if (num_visible_kids > 1)
			size.height += (num_visible_kids - 1) * spacing;
		return size;
	}

	// Other LayoutManager(2) methods that are unused by this class
	public void addLayoutComponent(String constraint, Component comp) {
	}

	public void addLayoutComponent(Component comp, Object constraint) {
	}

	public void removeLayoutComponent(Component comp) {
	}

	public void invalidateLayout(Container parent) {
	}

	public float getLayoutAlignmentX(Container parent) {
		return 0.5f;
	}

	public float getLayoutAlignmentY(Container parent) {
		return 0.5f;
	}
}

class ColumnLayoutPane extends JPanel {
	public ColumnLayoutPane() {
		// Get rid of the default layout manager.
		// We'll arrange the components ourselves.
		this.setLayout(new ColumnLayout(5, 5, 10, ColumnLayout.RIGHT));

		// Create some buttons and set their sizes and positions explicitly
		for (int i = 0; i < 6; i++) {
			int pointsize = 8 + i * 2;
			JButton b = new JButton("Point size " + pointsize);
			b.setFont(new Font("helvetica", Font.BOLD, pointsize));
			this.add(b);
		}
	}

	public static void main(String[] a) {
		JFrame f = new JFrame();
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});

		f.setContentPane(new ColumnLayoutPane());
		f.pack();
		f.setVisible(true);
	}

}
